﻿define([
    'Wjs/core/types'
],
function (types) {
    'use strict';

    // Dictionary to store the cache mapped by the type string
    var cache = {};

    return {

        // Registers a type mapped by the type string
        registerType: function (ctor) {
            var type = ctor.type || ctor.prototype.type;

            if (cache[type]) {
                console.log('There is already registered a type of name: ' + type);
            }

            cache[type] = ctor;
        },

        // Retrieves the registered type
        getType: function (type, optional) {
            var t = cache[type];

            if (!t && !optional) {

                throw 'Must include module for type: ' + type;
            }

            return t;
        },

        // Creates an instance of a component using its type, configuration, parent and owner
        create: function (conf, type, parent) {
            var t, instance;
            
            if (!types.isString(conf)) { // If the configuration is an empty string, we want to create an empty content
                conf = conf || {};
            }

            t = conf.type || type || parent.defaultChildType;

            if (!t) {
                throw 'Type must be provided either in the configuration or as a parameter';
            }

            var ctor = this.getType(t);

            if (!ctor) {
                throw 'Must include module for type: ' + t;
            }

            instance = new ctor(conf, parent);

            if (instance.createHandler) { // If there is an createHandler method in the instance, then call it
                instance.createHandler();
            }

            return instance;
        }
    };

});